package system

import (
	"context"
	"encoding/json"
	"errors"
	"github.com/flipped-aurora/gin-vue-admin/server/global"
	"github.com/flipped-aurora/gin-vue-admin/server/model/system"
	"github.com/flipped-aurora/gin-vue-admin/server/model/system/request"
	"go.uber.org/zap"
	"time"
)

//@author: [piexlmax](https://github.com/piexlmax)
//@function: CreateSysDictionaryDetail
//@description: 创建字典详情数据
//@param: sysDictionaryDetail model.SysDictionaryDetail
//@return: err error

type DictionaryDetailService struct{}

var DictionaryDetailServiceApp = new(DictionaryDetailService)

func (dictionaryDetailService *DictionaryDetailService) CreateSysDictionaryDetail(sysDictionaryDetail system.SysDictionaryDetail) (err error) {
	err = global.GVA_DB.Create(&sysDictionaryDetail).Error
	return err
}

//@author: [piexlmax](https://github.com/piexlmax)
//@function: DeleteSysDictionaryDetail
//@description: 删除字典详情数据
//@param: sysDictionaryDetail model.SysDictionaryDetail
//@return: err error

func (dictionaryDetailService *DictionaryDetailService) DeleteSysDictionaryDetail(sysDictionaryDetail system.SysDictionaryDetail) (err error) {
	err = global.GVA_DB.Delete(&sysDictionaryDetail).Error
	return err
}

//@author: [piexlmax](https://github.com/piexlmax)
//@function: UpdateSysDictionaryDetail
//@description: 更新字典详情数据
//@param: sysDictionaryDetail *model.SysDictionaryDetail
//@return: err error

func (dictionaryDetailService *DictionaryDetailService) UpdateSysDictionaryDetail(sysDictionaryDetail *system.SysDictionaryDetail) (err error) {
	err = global.GVA_DB.Save(sysDictionaryDetail).Error
	return err
}

//@author: [piexlmax](https://github.com/piexlmax)
//@function: GetSysDictionaryDetail
//@description: 根据id获取字典详情单条数据
//@param: id uint
//@return: sysDictionaryDetail system.SysDictionaryDetail, err error

func (dictionaryDetailService *DictionaryDetailService) GetSysDictionaryDetail(id uint) (sysDictionaryDetail system.SysDictionaryDetail, err error) {
	err = global.GVA_DB.Where("id = ?", id).First(&sysDictionaryDetail).Error
	return
}

//@author: [piexlmax](https://github.com/piexlmax)
//@function: GetSysDictionaryDetailInfoList
//@description: 分页获取字典详情列表
//@param: info request.SysDictionaryDetailSearch
//@return: list interface{}, total int64, err error

func (dictionaryDetailService *DictionaryDetailService) GetSysDictionaryDetailInfoList(info request.SysDictionaryDetailSearch) (list interface{}, total int64, err error) {
	limit := info.PageSize
	offset := info.PageSize * (info.Page - 1)
	// 创建db
	db := global.GVA_DB.Model(&system.SysDictionaryDetail{})
	var sysDictionaryDetails []system.SysDictionaryDetail
	// 如果有条件搜索 下方会自动创建搜索语句
	if info.Label != "" {
		db = db.Where("label LIKE ?", "%"+info.Label+"%")
	}
	if info.Value != "" {
		db = db.Where("value = ?", info.Value)
	}
	if info.Status != nil {
		db = db.Where("status = ?", info.Status)
	}
	if info.SysDictionaryID != 0 {
		db = db.Where("sys_dictionary_id = ?", info.SysDictionaryID)
	}
	if info.ParentID != nil {
		db = db.Where("parent_id = ?", *info.ParentID)
	}

	err = db.Count(&total).Error
	if err != nil {
		return
	}

	// 如果需要树形结构，则查询所有数据并构建树
	if info.IsTree {
		err = db.Order("sort").Find(&sysDictionaryDetails).Error
		if err != nil {
			return
		}

		// 构建树形结构
		var treeList []system.SysDictionaryDetail
		for i := range sysDictionaryDetails {
			if sysDictionaryDetails[i].ParentID == nil {
				err = dictionaryDetailService.buildTree(&sysDictionaryDetails[i], uint(info.SysDictionaryID))
				if err != nil {
					return nil, 0, err
				}
				treeList = append(treeList, sysDictionaryDetails[i])
			}
		}
		return treeList, int64(len(treeList)), nil
	}

	// 普通分页查询
	err = db.Limit(limit).Offset(offset).Order("sort").Find(&sysDictionaryDetails).Error
	return sysDictionaryDetails, total, err
}

// 按照字典id获取字典全部内容的方法
func (dictionaryDetailService *DictionaryDetailService) GetDictionaryList(dictionaryID uint) (list []system.SysDictionaryDetail, err error) {
	var sysDictionaryDetails []system.SysDictionaryDetail
	err = global.GVA_DB.Find(&sysDictionaryDetails, "sys_dictionary_id = ?", dictionaryID).Error
	return sysDictionaryDetails, err
}

// 按照字典type获取字典全部内容的方法
func (dictionaryDetailService *DictionaryDetailService) GetDictionaryListByType(t string) (list []system.SysDictionaryDetail, err error) {
	var sysDictionaryDetails []system.SysDictionaryDetail
	db := global.GVA_DB.Model(&system.SysDictionaryDetail{}).Joins("JOIN sys_dictionaries ON sys_dictionaries.id = sys_dictionary_details.sys_dictionary_id")
	err = db.Debug().Find(&sysDictionaryDetails, "type = ?", t).Error
	return sysDictionaryDetails, err
}

// 按照字典id+字典内容value获取单条字典内容
func (dictionaryDetailService *DictionaryDetailService) GetDictionaryInfoByValue(dictionaryID uint, value string) (detail system.SysDictionaryDetail, err error) {
	var sysDictionaryDetail system.SysDictionaryDetail
	err = global.GVA_DB.First(&sysDictionaryDetail, "sys_dictionary_id = ? and value = ?", dictionaryID, value).Error
	return sysDictionaryDetail, err
}

// 按照字典type+字典内容value获取单条字典内容
func (dictionaryDetailService *DictionaryDetailService) GetDictionaryInfoByTypeValue(t string, value string) (detail system.SysDictionaryDetail, err error) {
	var sysDictionaryDetails system.SysDictionaryDetail
	db := global.GVA_DB.Model(&system.SysDictionaryDetail{}).Joins("JOIN sys_dictionaries ON sys_dictionaries.id = sys_dictionary_details.sys_dictionary_id")
	err = db.First(&sysDictionaryDetails, "sys_dictionaries.type = ? and sys_dictionary_details.value = ?", t, value).Error
	return sysDictionaryDetails, err
}

// 获取级联树形结构的字典详情
func (dictionaryDetailService *DictionaryDetailService) GetDictionaryDetailTree(req request.SysDictionaryDetailTreeRequest) (list []system.SysDictionaryDetail, err error) {
	var sysDictionaryDetails []system.SysDictionaryDetail

	// 查询顶级节点（parent_id为NULL）
	if req.ParentID == nil {
		err = global.GVA_DB.Where("sys_dictionary_id = ? AND parent_id IS NULL", req.SysDictionaryID).
			Order("sort").
			Find(&sysDictionaryDetails).Error
	} else {
		// 查询指定父级下的子节点
		err = global.GVA_DB.Where("sys_dictionary_id = ? AND parent_id = ?", req.SysDictionaryID, *req.ParentID).
			Order("sort").
			Find(&sysDictionaryDetails).Error
	}

	if err != nil {
		return nil, err
	}

	// 递归构建树形结构
	for i := range sysDictionaryDetails {
		err = dictionaryDetailService.buildTree(&sysDictionaryDetails[i], req.SysDictionaryID)
		if err != nil {
			return nil, err
		}
	}

	return sysDictionaryDetails, nil
}

// 递归构建树形结构
func (dictionaryDetailService *DictionaryDetailService) buildTree(node *system.SysDictionaryDetail, dictionaryID uint) error {
	var children []system.SysDictionaryDetail
	err := global.GVA_DB.Where("sys_dictionary_id = ? AND parent_id = ?", dictionaryID, node.ID).
		Order("sort").
		Find(&children).Error

	if err != nil {
		return err
	}

	if len(children) > 0 {
		// 递归构建子节点的树形结构
		for i := range children {
			err = dictionaryDetailService.buildTree(&children[i], dictionaryID)
			if err != nil {
				return err
			}
		}
		node.Children = children
	}

	return nil
}

// GetFullDictionaryDetailTree 获取完整的级联树形结构（包含所有层级）
func (dictionaryDetailService *DictionaryDetailService) GetFullDictionaryDetailTree(dictionaryID uint) (list []system.SysDictionaryDetail, err error) {
	// 1. 定义缓存键
	cacheKey := "major_tree_" + string(dictionaryID)

	// 2. 尝试从Redis获取缓存
	if global.GVA_CONFIG.System.UseRedis && global.GVA_REDIS != nil {
		// 从Redis获取缓存的JSON字符串
		cachedData, err := global.GVA_REDIS.Get(context.Background(), cacheKey).Result()
		if err == nil {
			// 缓存命中，反序列化数据
			if err := json.Unmarshal([]byte(cachedData), &list); err == nil {
				// 为缓存续命，设置为1天过期
				global.GVA_REDIS.Expire(context.Background(), cacheKey, 24*time.Hour)
				return list, nil
			}
			// 反序列化失败，记录错误但继续查询数据库
			global.GVA_LOG.Error("从缓存反序列化专业树数据失败", zap.Error(err))
		}
	}

	// 3. 缓存未命中，执行原有的数据库查询逻辑
	var sysDictionaryDetails []system.SysDictionaryDetail

	// 查询所有顶级节点
	err = global.GVA_DB.Where("sys_dictionary_id = ? AND parent_id IS NULL", dictionaryID).
		Order("sort").
		Find(&sysDictionaryDetails).Error

	if err != nil {
		return nil, err
	}

	// 递归构建完整的树形结构
	for i := range sysDictionaryDetails {
		err = dictionaryDetailService.buildTree(&sysDictionaryDetails[i], dictionaryID)
		if err != nil {
			return nil, err
		}
	}

	// 4. 将查询结果存入Redis，设置1天过期时间
	if global.GVA_CONFIG.System.UseRedis && global.GVA_REDIS != nil && err == nil {
		// 序列化数据为JSON
		jsonData, err := json.Marshal(sysDictionaryDetails)
		if err == nil {
			// 存入Redis，过期时间设为24小时
			err = global.GVA_REDIS.Set(context.Background(), cacheKey, string(jsonData), 24*time.Hour).Err()
			if err != nil {
				// 缓存设置失败，记录错误但不影响返回结果
				global.GVA_LOG.Error("设置专业树缓存失败", zap.Error(err))
			}
		} else {
			global.GVA_LOG.Error("序列化专业树数据失败", zap.Error(err))
		}
	}

	return sysDictionaryDetails, nil
}

// 在 DictionaryDetailService 结构体中添加新方法
// GetTopLevelDictionaryDetails 只获取顶级字典详情，不构建树形结构
func (dictionaryDetailService *DictionaryDetailService) GetTopLevelDictionaryDetails(dictionaryID uint) (list []system.SysDictionaryDetail, err error) {
	var sysDictionaryDetails []system.SysDictionaryDetail

	// 只查询顶级节点，不进行递归
	err = global.GVA_DB.Where("sys_dictionary_id = ? AND parent_id IS NULL", dictionaryID).
		Order("sort").
		Find(&sysDictionaryDetails).Error

	return sysDictionaryDetails, err
}

// GetDirectChildrenByParentID 只获取指定父ID的直接子节点，不构建树形结构
func (dictionaryDetailService *DictionaryDetailService) GetDirectChildrenByParentID(dictionaryID uint, parentID uint) (list []system.SysDictionaryDetail, err error) {
	var sysDictionaryDetails []system.SysDictionaryDetail

	// 只查询指定父ID的直接子节点，不进行递归
	err = global.GVA_DB.Where("sys_dictionary_id = ? AND parent_id = ?", dictionaryID, parentID).
		Order("sort").
		Find(&sysDictionaryDetails).Error

	return sysDictionaryDetails, err
}

// GetTopLevelParentID 根据子节点ID递归查找顶级父节点ID
// 用于从专业ID向上查找专业大类ID（字典树的顶级节点）
func (dictionaryDetailService *DictionaryDetailService) GetTopLevelParentID(nodeID uint) (uint, error) {
	// 验证节点ID
	if nodeID == 0 {
		return 0, errors.New("节点ID无效")
	}
	
	// 获取当前节点信息
	var currentNode system.SysDictionaryDetail
	err := global.GVA_DB.Where("id = ?", nodeID).First(&currentNode).Error
	if err != nil {
		return 0, err
	}
	
	// 如果当前节点没有父节点（parentID为nil），则它自己就是顶级节点
	if currentNode.ParentID == nil {
		return nodeID, nil
	}
	
	// 递归查找父节点的顶级节点
	return dictionaryDetailService.GetTopLevelParentID(*currentNode.ParentID)
}

// GetMajorCategoryID 根据专业ID获取其所属的专业大类ID
// 专门用于处理专业字典（字典ID为9）中的专业到专业大类的映射
func (dictionaryDetailService *DictionaryDetailService) GetMajorCategoryID(majorID uint) (uint, error) {
	// 验证专业ID
	if majorID == 0 {
		return 0, errors.New("专业ID无效")
	}
	
	// 验证该ID是否属于专业字典（字典ID为9）
	var majorNode system.SysDictionaryDetail
	err := global.GVA_DB.Where("id = ? AND sys_dictionary_id = 9", majorID).First(&majorNode).Error
	if err != nil {
		return 0, errors.New("专业ID不存在或不属于专业字典")
	}
	
	// 调用通用的顶级父节点查找函数
	return dictionaryDetailService.GetTopLevelParentID(majorID)
}
